package com.ytjj.qmyx.supplychain.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.google.gson.Gson;
import com.kuaidi100.sdk.api.QueryTrack;
import com.kuaidi100.sdk.enums.ExpressEnums;
import com.kuaidi100.sdk.request.QueryTrackParam;
import com.kuaidi100.sdk.request.QueryTrackReq;
import com.kuaidi100.sdk.response.QueryTrackData;
import com.kuaidi100.sdk.response.QueryTrackResp;
import com.kuaidi100.sdk.utils.PropertiesReader;
import com.kuaidi100.sdk.utils.SignUtils;
import com.ytjj.common.dto.mqdto.SmsDto;
import com.ytjj.qmyx.supplychain.common.api.CommonPage;
import com.ytjj.qmyx.supplychain.common.constants.QueueConstants;
import com.ytjj.qmyx.supplychain.common.constants.RedisConstants;
import com.ytjj.qmyx.supplychain.common.enums.ExpressOrderInvalidFlagEnums;
import com.ytjj.qmyx.supplychain.common.enums.NeedPhoneExpressEnum;
import com.ytjj.qmyx.supplychain.common.model.request.ExpressOrderRequest;
import com.ytjj.qmyx.supplychain.common.utils.DateUtil;
import com.ytjj.qmyx.supplychain.common.utils.ExpressDicUtil;
import com.ytjj.qmyx.supplychain.common.utils.RedisService;
import com.ytjj.qmyx.supplychain.common.utils.feishu.FeiShuUtil;
import com.ytjj.qmyx.supplychain.mapper.*;
import com.ytjj.qmyx.supplychain.mapper.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Nullable;
import javax.annotation.Resource;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
@RefreshScope
public class ExpressOrderService extends AbstractService<ExpressOrdersMapper, YxExpressOrders> {
    @Resource
    private ExpressOrdersMapper expressOrdersMapper;
    @Resource
    private OrdersMapper ordersMapper;
    @Resource
    private BankerOrderMapper bankerOrderMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private OrderExceptionMapper orderExceptionMapper;
    @Resource
    private BankerMapper bankerMapper;
    @Resource
    private ReturnGoodsMapper returnGoodsMapper;
    @Resource
    private RedisService redisService;
    @Resource
    private OrderService orderService;
    @Resource
    private ReissueLogisticsMapper reissueLogisticsMapper;
    @Resource
    private MqProducerService mqProducerService;

    @Value("${expressStatus.threshold:72}")
    private String expressStatusThreshold;
    @Value("${expressStatus.noExpressCheckInterval:24}")
    private Integer noExpressCheckInterval;
    @Value("${expressStatus.noExpressCheckInterval2:48}")
    private Integer noExpressCheckInterval2;
    @Value("${expressStatus.noExpressCheckInterval3:72}")
    private Integer noExpressCheckInterval3;
    @Value("${santong.account:}")
    private String stAccount;
    @Value("${santong.password:}")
    private String stPassword;
    @Value("${santong.sign:【xxxx】}")
    private String stSign;
    @Value("${santong.url:}")
    private String stUrl;
    @Value("${checkShopFlag:true}")
    private boolean checkShopFlag;
    //不需要发送短信账号
    @Value("${ignoreShopId:GUOB004,QMYX001,QMYX002}")
    private String ignoreShopId;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    @Lazy
    private ExpressOrderService thisProxy;
    /**
     * 快递更新时间差值 30分钟
     */
    private static final long DIFFERENCE_VALUE = 1800L;

    /**
     * 扫描供应商订单表有快递单号，但是没有同步到物流表的数据，然后同步到物流表,
     * 并向快递100发起订阅
     */
    public void expressInfoBack() {
        //临时处理方案,key-供应商id, value-寄件人手机号（只针对顺丰订单才需要设置寄件人）
        Map<Integer,String> merchantPackageSender = new HashMap<>();
        merchantPackageSender.put(1345,"18123609487");
        LocalDateTime ldt = LocalDateTime.now(ZoneId.systemDefault());
        ldt = ldt.minusMonths(2);
        Date date = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
        // 挑选出供应商近两个月系统平台订单
        Example example = new Example(YxBankerOrder.class);
        example.createCriteria().andGreaterThanOrEqualTo("createTime", date).andEqualTo("isNewSync", 0).andIsNotNull("expressNo").andIsNotNull("expressCode");
        List<YxBankerOrder> bankerOrderList = bankerOrderMapper.selectByExample(example);
        bankerOrderList.parallelStream().forEach(item -> {
            // 获取锁
            RLock lock = redissonClient.getLock("orderExpress:" + item.getExpressCode() + "_" + item.getExpressNo());
            try {
                boolean b = lock.tryLock(0, 5, TimeUnit.SECONDS);
                if (b) {
                    // 插入快递表
                    Example expressOrderExample = new Example(YxExpressOrders.class);
                    expressOrderExample.createCriteria().andEqualTo("companyNo", item.getExpressCode()).andEqualTo("expressEno", item.getExpressNo());
                    List<YxExpressOrders> expressOrders = expressOrdersMapper.selectByExample(expressOrderExample);
                    if (CollectionUtils.isEmpty(expressOrders)) {
                        YxExpressOrders yxExpressOrders = new YxExpressOrders();
                        yxExpressOrders.setCompanyNo(item.getExpressCode());
                        yxExpressOrders.setExpressEno(item.getExpressNo().replaceAll("\\u00A0+|",""));
                        yxExpressOrders.setAddress(item.getDeliveryAddress());
                        //特定供应商，且发的顺丰快递，则需要设置寄件人手机号
                        if(yxExpressOrders.getExpressEno().startsWith("SF") && null != merchantPackageSender.get(item.getBankerId())){
                            yxExpressOrders.setPhone(merchantPackageSender.get(item.getBankerId()));
                        }else {
                            yxExpressOrders.setPhone(item.getUserTel());
                        }
                        yxExpressOrders.setCreateTime(new Date());
                        yxExpressOrders.setUpdateTime(new Date());
                        yxExpressOrders.setType(1);
                        yxExpressOrders.setInvalidFlag(ExpressOrderInvalidFlagEnums.YES.getValue());
                        yxExpressOrders.setStatus(-2);
                        expressOrdersMapper.insertSelective(yxExpressOrders);
                        orderService.subscribeExpress(item.getExpressNo(), item.getExpressCode(), item.getUserTel());
                    }
                    // 更改状态
                    YxBankerOrder yxBankerOrder = new YxBankerOrder();
                    yxBankerOrder.setId(item.getId());
                    yxBankerOrder.setIsNewSync((byte) 1);
                    yxBankerOrder.setUpdateTime(new Date());
                    bankerOrderMapper.updateByPrimaryKeySelective(yxBankerOrder);
                }
            } catch (Exception e) {
                lock.unlock();
                log.error("保存订单到物流表的数据出错{}",e);
            }
        });
    }




    /**
     * 查询一段时间内未发货订单,已下单时间为维度
     * @param type 1：2-6天内   2：7-30天内
     * @return List<YxBankerOrder>
     */
    public List<YxBankerOrder> queryBankerOrderList(int type) {
        if (1 == type) {
            return bankerOrderMapper.queryBankerOrderListBy6Day();
        } else if (2 == type) {
            return bankerOrderMapper.queryBankerOrderListBy30Day();
        } else {
            return bankerOrderMapper.queryBankerOrderListGt30Day();
        }
    }



    /**
     * 根据物流响应处理快递和订单数据
     * @param resp
     */
    public void handleExpressResp(QueryTrackResp resp, YxExpressOrders expressOrders) {
        //原来有物流，最新查询的又显示无物流，则不更新数据
        if(!ExpressEnums.NO_EXPRESS_DETAIL.getStatus().equals(String.valueOf(expressOrders.getStatus())) && !"200".equals(resp.getStatus())){
            log.info("快递：%s,%s原来有物流，现在快递100返回查无物流。注意排查~", expressOrders.getCompanyNo(), expressOrders.getExpressEno());
            return;
        }
        expressOrders.setResText(JSONObject.toJSONString(resp));
        expressOrders.setMessage(resp.getMessage());
        expressOrders.setUpdateTime(new Date());
        if ("200".equals(resp.getStatus())) {
            // 1.更新物流表
            expressOrders.setInfoText(CollectionUtils.isEmpty(resp.getData()) ? null : JSONObject.toJSONString(resp.getData()));
            if(ExpressEnums.isCheck(resp.getState())){
                expressOrders.setIsCheck(1);
                expressOrders.setCheckTime(DateUtil.StrToTime(resp.getData().get(0).getFtime()));
            }else {
                expressOrders.setCheckTime(null);
                expressOrders.setIsCheck(0);
            }
            expressOrders.setStatus(Integer.valueOf(Optional.ofNullable(resp.getState()).orElse("-2")));
            expressOrders.setExpressStatus(resp.getStatus());
            // 2.更新供应商订单表物流，订单状态放后面去处理
            YxBankerOrder newBankerOrder = new YxBankerOrder();
            newBankerOrder.setExpressNo(resp.getNu());
            newBankerOrder.setExpressCode(resp.getCom());
            newBankerOrder.setExpressRecord(CollectionUtils.isEmpty(resp.getData()) ? null : JSONObject.toJSONString(resp.getData()));
            if (StringUtils.isNotEmpty(ExpressEnums.getRefundStatus(resp.getState()))) {
                newBankerOrder.setIsRejection(1);
            } else {
                newBankerOrder.setIsRejection(0);
            }
            bankerOrderMapper.updateByExpress(newBankerOrder);
        }else {
            expressOrders.setStatus(-2);
        }
        expressOrdersMapper.updateByPrimaryKey(expressOrders);
        //3.处理异常订单
        thisProxy.handleExceptionOrder(resp,expressOrders);
    }


    /**
     * 更新订单的签收和拒签状态
     */
    public void updateOrdersByTrackData(String childOrderNo, QueryTrackResp resp) {
        //状态正常
        if ("200".equals(resp.getStatus())) {
            //签收或者退签，才需要更新订单
            if (ExpressEnums.isCheck(resp.getState()) || ExpressEnums.WITHDRAWAL.getStatus().equals(resp.getState())) {
                Example example = new Example(YxOrders.class);
                example.createCriteria().andEqualTo("childOrderNo", childOrderNo);
                List<YxOrders> ordersList = ordersMapper.selectByExample(example);
                List<QueryTrackData> queryTrackData = resp.getData();
                if (ExpressEnums.isCheck(resp.getState())) {
                    for (YxOrders yxOrder : ordersList) {
                        YxOrders newOrders = new YxOrders();
                        newOrders.setId(yxOrder.getId());
                        newOrders.setReturnReceiveStatus(0);
                        newOrders.setReturnReceiveTime(null);
                        newOrders.setReceiveStatus(1);
                        //签收时间不存在则取当前时间，否则取最新物流时间
                        newOrders.setReceiveTime(CollectionUtils.isEmpty(queryTrackData) ? new Date() : DateUtil.StrToTime(queryTrackData.get(0).getFtime()));
                        ordersMapper.updateOrderColumnById(newOrders);
                    }
                } else if (ExpressEnums.WITHDRAWAL.getStatus().equals(resp.getState())) {//快递退回签收
                    QueryTrackData queryTrackData1 = queryTrackData.get(0);
                    if(null == queryTrackData1){
                        return;
                    }
                    if(ExpressEnums.isCheck(queryTrackData1.getStatusCode()) || ExpressEnums.WITHDRAWAL.getStatus().equals(resp.getState())){
                        for (YxOrders yxOrder : ordersList) {
                            YxOrders newOrders = new YxOrders();
                            newOrders.setId(yxOrder.getId());
                            newOrders.setReceiveTime(null);
                            newOrders.setReceiveStatus(0);
                            newOrders.setReturnReceiveStatus(1);
                            //退签时间不存在则取当前时间，否则取最新物流时间
                            newOrders.setReturnReceiveTime(CollectionUtils.isEmpty(queryTrackData) ? new Date() : DateUtil.StrToTime(queryTrackData.get(0).getFtime()));
                            ordersMapper.updateOrderColumnById(newOrders);
                        }
                    }
                }
            }
        }
    }

    /**
     * 根据快递单号，快递公司查询订单
     * @param expressCode
     * @param expressNo
     * @return List<YxBankerOrder>
     */
    public List<YxBankerOrder> getBankOrderByExpressNo(String expressCode, String expressNo) {
        List<YxBankerOrder> bankerOrderList = bankerOrderMapper.getBankerOrdersByExpressNo(expressNo, expressCode);
        if (bankerOrderList.size() > 0) {
            return bankerOrderList;
        }
        return null;
    }

    public void saveExceptionOrder(YxBankerOrder order, String desc,QueryTrackResp resp) {
        YxOrderException orderException = new YxOrderException();
        BeanUtils.copyProperties(order, orderException);
        orderException.setExceptionDesc(desc);
        orderException.setStatusCode(resp == null ? null : Integer.valueOf(resp.getState()));
        orderException.setExpressRecord(JSON.toJSONString(resp));
        if (null != order.getBankerId()) {
            YxBanker banker = bankerMapper.selectByPrimaryKey(order.getBankerId());
            orderException.setBankerName(banker.getName());
        }
        orderException.setOrderOn(order.getOrderNo());
        orderException.setOrderCreateTime(order.getCreateTime());
        orderException.setCreateTime(new Date());
        orderException.setTaskUpdateTime(new Date());
        orderException.setStatus((byte) 1);
        orderExceptionMapper.insertSelective(orderException);
    }



    /**
     * 根据快递响应处理异常订单
     * @param resp 物流报文
     */
    @Transactional(rollbackFor = Exception.class)
    public void handleExceptionOrder(QueryTrackResp resp,YxExpressOrders expressOrders) {
        //多个订单可以是一个包裹
        List<YxBankerOrder> yxBankerOrder = getBankOrderByExpressNo(expressOrders.getCompanyNo(), expressOrders.getExpressEno());
        if (null == yxBankerOrder) {
//            FeiShuUtil.sendMsg("处理异常订单时，查询发货单对应的供应商订单不存在，快递信息:" + resp.getCom() + "," + resp.getNu());
            return;
        }
        List<YxBankerOrder> collect = yxBankerOrder.stream().filter(e -> (e.getOrderInfoStatus() == 1 || e.getOrderInfoStatus() == 2)).collect(Collectors.toList());
        //如果当前订单状态不是“已发货”和“待发货”，则不跟踪异常。
        if(collect.size() == 0){
            return;
        }
        for (YxBankerOrder bankerOrder : yxBankerOrder) {
            //更新订单数据
            thisProxy.updateOrdersByTrackData(bankerOrder.getChildOrderNo(),resp);
            YxBankerOrder newBankerOrder = new YxBankerOrder();
            newBankerOrder.setId(bankerOrder.getId());
            newBankerOrder.setStatus((byte) 2);
            //当前异常订单是是否存在
            YxOrderException yxOrderException = orderExceptionMapper.selectByPrimaryKey(bankerOrder.getId());
            if(yxOrderException != null && yxOrderException.getIsFinished() == 1){
                continue;
            }
            YxOrderException newOrderException = new YxOrderException();
            newOrderException.setId(bankerOrder.getId());
            newOrderException.setOrderOn(bankerOrder.getOrderNo());
            newOrderException.setProductName(bankerOrder.getProductName());
            newOrderException.setUserName(bankerOrder.getUserName());
            newOrderException.setUserTel(bankerOrder.getUserTel());
            newOrderException.setDeliveryAddress(bankerOrder.getDeliveryAddress());
            newOrderException.setBankerId(bankerOrder.getBankerId());
            newOrderException.setOrderCreateTime(bankerOrder.getCreateTime());
            newOrderException.setNote(bankerOrder.getNote());
            //设置最新物流单号，可能订单物流已被修改
            newOrderException.setExpressCode(bankerOrder.getExpressCode());
            newOrderException.setExpressNo(bankerOrder.getExpressNo());
            newOrderException.setChildOrderNo(bankerOrder.getChildOrderNo());
            newOrderException.setTaskUpdateTime(new Date());
            newOrderException.setStatus(yxOrderException == null ? 1 : yxOrderException.getStatus());
            newOrderException.setIsFinished(yxOrderException == null ? 0 : yxOrderException.getIsFinished());
            newOrderException.setCreateTime(yxOrderException == null ? new Date() : yxOrderException.getCreateTime());
            if (null != bankerOrder.getBankerId()) {
                YxBanker banker = bankerMapper.selectByPrimaryKey(bankerOrder.getBankerId());
                newOrderException.setBankerName(banker.getName());
            }
            //处理物流数据
            if ("200".equals(resp.getStatus())) {//状态正常
                newOrderException.setExpressRecord(CollectionUtils.isEmpty(resp.getData()) ? null : JSON.toJSONString(resp.getData()));
                newOrderException.setStatusCode(Integer.valueOf(Optional.ofNullable(resp.getState()).orElse("-2")));
                newOrderException.setStatusDesc(ExpressEnums.getStatusName(resp.getState()));
                //最新的时间
                Date latestFDate = DateUtil.StrToTime(resp.getData().get(0).getFtime());
                //最早的时间
                Date earliestDate = DateUtil.StrToTime(resp.getData().get(resp.getData().size() - 1).getFtime());
                boolean caseOne = isBetween(48L, 72L, latestFDate);
                boolean caseTwo = isBetween(72L, null, latestFDate);
                //异常已处理文案
                String successDesc = "异常订单已恢复正常：" + ExpressEnums.getStatusName(resp.getState());
                //是否存在【投柜或驿站】状态,有则记录送达地址
                List<QueryTrackData> data = resp.getData();
                if(!CollectionUtils.isEmpty(data)){
                    AtomicLong time  = new AtomicLong();
                    data.stream().forEach(e->{
                        if(ExpressEnums.DELIVERY_COUNTER_OR_STATION.getStatus().equals(e.getStatusCode())){
                            Date date = DateUtil.StrToTime(e.getFtime());
                            if(time.get() < date.getTime()){
                                newOrderException.setArrivalAddress(e.getContext());
                                newOrderException.setArrivalTime(date);
                                time.set(date.getTime());
                            }
                        }
                    });
                }
                if (ExpressEnums.isCheck(resp.getState())) {//快递已签收
                    newBankerOrder.setStatus((byte) 3);
                    newOrderException.setStatus((byte) 2);
                    newOrderException.setExceptionDesc(successDesc);
                    if(yxOrderException != null){
                        yxOrderException.setHandleTime(new Date());
                        yxOrderException.setHandlePerson(null);
                    }
                }
                //是否超10天未送达，排除待签收、已拒收/退回。
                else if (!isFilterForUndelivered(resp) && isTimeOut(earliestDate, 24 * 10)) {
                    if (yxOrderException != null) {
                        Date handleTime = yxOrderException.getHandleTime();
                        if (!isTimeOut(handleTime, 24)) {
                            log.info("===距离上次处理不到24小时，不更新当前异常订单，id==={}", yxOrderException.getId());
                            continue;
                        }
                    }
                    newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.DELIVERY_TIMEOUT.getStatus()));
                    newOrderException.setStatusDesc(ExpressEnums.DELIVERY_TIMEOUT.getStatusName());
                    newOrderException.setStatus((byte) 1);
                    newOrderException.setExceptionDesc("快递状态异常：超10天未送达");
                } else if (StringUtils.isNotEmpty(ExpressEnums.getExceptionName(resp.getState()))) {//快递状态异常
                    String desc = "快递状态异常："+ExpressEnums.getStatusName(resp.getState());
                    if (yxOrderException != null) {
                        Date handleTime = yxOrderException.getHandleTime();
                        if(!isTimeOut(handleTime,24)){
                            log.info("===距离上次处理不到24小时，不更新当前异常订单，id==={}", yxOrderException.getId());
                            continue;
                        }
                    }
                    //超时未更新或者疑难
                    if(ExpressEnums.TIMED_OUT_NOT_UPDATED.getStatus().equals(resp.getState()) || ExpressEnums.DIFFICULT.getStatus().equals(resp.getState())){
                        if(isReject(resp.getData())){
                            desc = "快递状态异常：已拒收";
                            newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.REJECTION.getStatus()));
                            newOrderException.setStatusDesc(ExpressEnums.getStatusName(ExpressEnums.REJECTION.getStatus()));
                        }else if(isReturn(resp.getData())){
                            desc = "快递状态异常：退回中";
                            newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.RETURN_BACK.getStatus()));
                            newOrderException.setStatusDesc(ExpressEnums.getStatusName(ExpressEnums.RETURN_BACK.getStatus()));
                        }else if(isTimeOut(latestFDate,48) && !isReceived(resp.getData().get(0).getContext())){
                            //超时未更新不包括揽收超时，揽收超时需要单独处理
                            desc = caseOne ? "物流超48小时未更新" : caseTwo ? "物流超72小时未更新" : "物流超时未更新";
                            newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.TIMED_OUT_NOT_UPDATED.getStatus()));
                            newOrderException.setStatusDesc(ExpressEnums.getStatusName(ExpressEnums.TIMED_OUT_NOT_UPDATED.getStatus()));
                        }else if(isDelivery(resp.getData().get(0).getContext())) {
                            //文字匹配，将第三方的默认超时状态，修改成适用于我们的超时未签收
                            newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatus()));
                            newOrderException.setStatusDesc(ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatusName());
                            desc = "快递状态异常：" + ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatusName();
                        } else if (isReceived(resp.getData().get(0).getContext())) {
                            if (caseOne || caseTwo) {
                                desc = caseOne ? "物流超48小时一直处于已揽收" : caseTwo ? "物流超72小时一直处于已揽收" : "物流超时一直处于已揽收";
                            }
                        } else {
                            if (caseOne || caseTwo) {
                                desc = caseOne ? "物流超48小时未更新" : caseTwo ? "物流超72小时未更新" : "物流超时未更新";
                            }
                        }
                    }
                    //超时未揽收
                    else if(ExpressEnums.TIMEOUT_PENDING_COLLECTION.getStatus().equals(resp.getState()) && isTimeOut(latestFDate,24)){
                        desc = "超24小时待揽收，查无物流";
                        newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.NO_EXPRESS_DETAIL.getStatus()));
                        newOrderException.setStatusDesc(ExpressEnums.NO_EXPRESS_DETAIL.getStatusName());
                    }
                    newOrderException.setStatus((byte)1);
                    newOrderException.setExceptionDesc(desc);
                } else {//其他状态
                    if (StringUtils.isNotEmpty(ExpressEnums.getCollectByStatus(resp.getState()))) {//揽收
                        if (yxOrderException != null) {
                            Date handleTime = yxOrderException.getHandleTime();
                            if(!isTimeOut(handleTime,24)){
                                log.info("===距离上次处理不到24小时，不更新当前异常订单，id==={}", yxOrderException.getId());
                                continue;
                            }
                        }
                        if(!isTimeOut(latestFDate,24)){//不超过24小时
                            if (yxOrderException == null) {
                                continue;
                            }
                            //当前存在异常订单，且状态是揽收状态不超过24小时，则不记录为异常订单。
                            else if (StringUtils.isNotEmpty(ExpressEnums.getCollectByStatus(yxOrderException.getStatusCode().toString()))) {
                                log.info("===物流最新时间不超过24小时，且异常单一直处于揽收状态，不记录异常,订单号{}", bankerOrder.getChildOrderNo());
                                continue;
                            }
                        }else if(ExpressEnums.PENDING_COLLECTION.getStatus().equals((resp.getState()))){//待揽收超时
                            newOrderException.setExceptionDesc("待揽收已超24小时，查无物流");
                            newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.NO_EXPRESS_DETAIL.getStatus()));
                            newOrderException.setStatusDesc(ExpressEnums.NO_EXPRESS_DETAIL.getStatusName());
                        }else {//超过24小时
                            //如果是揽收中的已下单状态，需要特殊处理，因为快递100会返回物流文案："2023-10-13 14:17:46 已下单【该信息由快递100提供】"
                            if(ExpressEnums.ORDERED.getStatus().equals((resp.getState()))){
                                newOrderException.setExceptionDesc("待揽收已超24小时，查无物流");
                                newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.NO_EXPRESS_DETAIL.getStatus()));
                                newOrderException.setStatusDesc(ExpressEnums.NO_EXPRESS_DETAIL.getStatusName());
                            }else {
                                newOrderException.setExceptionDesc("一直处于揽收状态，超24小时未更新");
                                newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.TIMED_OUT_NOT_UPDATED.getStatus()));
                                newOrderException.setStatusDesc(ExpressEnums.TIMED_OUT_NOT_UPDATED.getStatusName());
                            }
                            newOrderException.setStatus((byte) 1);
                            newBankerOrder.setStatus((byte) 2);
                        }
                    } else if (StringUtils.isEmpty(resp.getState())) { //无状态
                        if (yxOrderException != null) {
                            Date handleTime = yxOrderException.getHandleTime();
                            if(!isTimeOut(handleTime,24)){
                                log.info("===距离上次处理不到24小时，不更新当前异常订单，id==={}", yxOrderException.getId());
                                continue;
                            }
                        }
                        newOrderException.setStatus((byte) 1);
                        newOrderException.setExceptionDesc("物流状态异常，无状态！");
                        newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.NO_EXPRESS_STATUS.getStatus()));
                        newOrderException.setStatusDesc(ExpressEnums.NO_EXPRESS_STATUS.getStatusName());
                        newBankerOrder.setStatus((byte) 2);
                    } else {//正常的状态
                        //在途物流是否超48或72小时
                        if (StringUtils.isNotEmpty(ExpressEnums.getAllInTransit(resp.getState())) && (caseOne || caseTwo)) {
                            String desc = caseOne ? "物流超48小时未更新" : caseTwo ? "物流超72小时未更新" : "物流超时未更新";
                            //处理时间是否超24小时
                            if (yxOrderException != null) {
                                Date handleTime = yxOrderException.getHandleTime();
                                if (!isTimeOut(handleTime, 24)) {
                                    continue;
                                }
                            }
                            if (isDelivery(resp.getData().get(0).getContext())) {//是否已送达
                                //已送达，但第三方的状态是正常状态，需要修改成适用于我们的异常状态："超时未签收"
                                newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatus()));
                                newOrderException.setStatusDesc(ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatusName());
                                desc = "快递状态异常："+ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatusName();
                            }else if(isMatchRegex(resp.getData(),Arrays.asList(".*?退回"))){
                                newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.RETURN_BACK.getStatus()));
                                newOrderException.setStatusDesc(ExpressEnums.RETURN_BACK.getStatusName());
                                desc = "快递状态异常："+ExpressEnums.RETURN_BACK.getStatusName();
                            }else if(isMatchRegex(resp.getData(),Arrays.asList(".*?拒收"))){
                                newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.REJECTION.getStatus()));
                                newOrderException.setStatusDesc(ExpressEnums.REJECTION.getStatusName());
                                desc = "快递状态异常："+ExpressEnums.REJECTION.getStatusName();
                            }else if(isMatchRegex(resp.getData(),Arrays.asList(".*?拒签"))){
                                newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.REFUSAL_TO_SIGN_FOR.getStatus()));
                                newOrderException.setStatusDesc(ExpressEnums.REFUSAL_TO_SIGN_FOR.getStatusName());
                                desc = "快递状态异常："+ExpressEnums.REFUSAL_TO_SIGN_FOR.getStatusName();
                            }else {
                                newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.TIMED_OUT_NOT_UPDATED.getStatus()));
                                newOrderException.setStatusDesc(ExpressEnums.TIMED_OUT_NOT_UPDATED.getStatusName());
                            }
                            log.info("===物流停超时未更新,订单号{}", bankerOrder.getChildOrderNo());
                            //有正常单则修改成异常单
                            newOrderException.setStatus((byte) 1);
                            newOrderException.setExceptionDesc(desc);
                            newBankerOrder.setStatus((byte) 2);
                        } else {
                            if (yxOrderException == null) {
                                log.info("===物流正常，不记录异常记录，childOrderNo==={}", bankerOrder.getChildOrderNo());
                                continue;
                            }
                            //有异常单则修改成正常单
                            newOrderException.setStatus((byte) 2);
                            newOrderException.setExceptionDesc(successDesc);
                            yxOrderException.setHandleTime(new Date());
                            newBankerOrder.setStatus((byte) 3);
                        }
                    }
                }
            } else {//快递返回状态非200
                log.debug("===快递100物流状态不为 200 ====resp==={}", resp);
                String exceptionDesc = "查无物流";
                Date importDate = bankerOrder.getImportTime();
                //是否正常
                boolean isNormal = false;
                if (importDate != null) {
                    long value = System.currentTimeMillis() - importDate.getTime();
                    long valueHour = value / 1000 / 3600;
                    if (valueHour >= 24 && valueHour < 48) {
                        exceptionDesc = "超24小时查无物流";
                    } else if (valueHour >= 48 && valueHour < 72) {
                        exceptionDesc = "超48小时查无物流";
                    } else if (valueHour >= 72) {
                        exceptionDesc = "超72小时查无物流";
                    }
                }
                if (yxOrderException != null) {
                    Date handleTime = yxOrderException.getHandleTime();
                    if(!isTimeOut(handleTime,24)){
                        log.info("===距离上次处理不到24小时，还是无物流，不更新当前异常订单,id==={}", yxOrderException.getId());
                        continue;
                    }
                    //距离发货时间不到24小时，原来异常订单状态是未录入快递单号，当前已发货，异常是查无物流，则修改成正常
                    if (yxOrderException.getStatusCode() == -1 && !isTimeOut(importDate, 24)) {
                        //有异常单则修改成正常单
                        newOrderException.setStatus((byte) 2);
                        newOrderException.setExceptionDesc("异常订单已恢复正常:当前异常订单已录入快递单号");
                        yxOrderException.setHandleTime(new Date());
                        newBankerOrder.setStatus((byte) 3);
                        isNormal = true;
                    }
                }
                if(!isNormal){
                    if (!isTimeOut(importDate, 24)) {
                        log.info("===距离发货时间不到24小时，无需记录查“无物流的异常”==={}", bankerOrder);
                        continue;
                    }
                    newOrderException.setStatus((byte)1);
                    newOrderException.setExpressRecord(null);
                    newOrderException.setStatusCode(Integer.valueOf(ExpressEnums.NO_EXPRESS_DETAIL.getStatus()));
                    newOrderException.setStatusDesc(ExpressEnums.NO_EXPRESS_DETAIL.getStatusName());
                    newOrderException.setExceptionDesc(exceptionDesc);
                }
            }

            if (yxOrderException == null) {
                if(newOrderException.getStatus() == 1){
                    newOrderException.setExceptionTime(new Date());
                    orderExceptionMapper.insertSelective(newOrderException);
                }
            } else {
                //再次出现异常
                if (newOrderException.getStatus() == 1) {
                    newOrderException.setExceptionTime(new Date());
                    yxOrderException.setHandleTime(null);
                    yxOrderException.setHandlePerson(null);
                }else {
                    newOrderException.setExceptionTime(yxOrderException.getExceptionTime());
                }
                newOrderException.setHandleTime(yxOrderException.getHandleTime());
                newOrderException.setHandlePerson(yxOrderException.getHandlePerson());
                newOrderException.setExceptionClassify(yxOrderException.getExceptionClassify());
                orderExceptionMapper.updateByPrimaryKey(newOrderException);
            }
            //如果是异常且有物流轨迹（需要发短信的异常类型都是有物流轨迹的），需要发送短信
            if (newOrderException.getStatus() == 1 && "200".equals(resp.getStatus())) {
                try {
                    String key = RedisConstants.EXCEPTION_EXPRESS_KEY+newOrderException.getExpressCode()+newOrderException.getExpressNo();
                    //最早的时间
                    Date firstDate = DateUtil.StrToTime(resp.getData().get(resp.getData().size() - 1).getFtime());
                    if (isTimeOut(firstDate, 24 * 7)) {
                        String content = setMsgContent(resp, resp.getState(), newOrderException.getExpressCode(), newOrderException.getExpressNo());
                        String exist = redisService.get(key);
                        //指定的异常才发送短信，且在缓存中不存在
                        if (StringUtils.isNotEmpty(content) && StringUtils.isEmpty(exist)) {
                            SmsDto smsDto = new SmsDto();
                            smsDto.setPhone(bankerOrder.getUserTel());
                            smsDto.setType(12);
                            smsDto.setCode(content);
                            smsDto.setChildOrderNo(newOrderException.getChildOrderNo());
                            mqProducerService.sendSms(smsDto, bankerOrder.getShopId());
                            redisService.set(key, "1", 20L, TimeUnit.DAYS);
                        }
                    }
                } catch (Exception e) {
                    log.error("物流异常短信发送失败：",e);
                    e.printStackTrace();
                }
            }
            bankerOrderMapper.updateByPrimaryKeySelective(newBankerOrder);
        }
    }

    /**
     * 设置短信模板
     */
    public String setMsgContent(QueryTrackResp resp,String status,String expressCode,String expressNo){
        //最新的时间
        String content = null;
        try {
            Date latestFDate = DateUtil.StrToTime(resp.getData().get(0).getFtime());
            String latestTrack = resp.getData().get(0).getContext().replace("【", "<").replace("】", ">");
            content = "";
            //超时未签收,柜或驿站超时未取
            if (ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatus().equals(status) || ExpressEnums.TIMED_OUT_NOT_GET.getStatus().equals(status)) {
                String baseContent = "您的包裹（%s%s）\n最新显示：%s %s\n特殊情况请联系平台客服";
                content = String.format(baseContent, ExpressDicUtil.getMapKey(expressCode), expressNo, DateUtil.dateToStr(latestFDate), latestTrack)+" %s";
            } else if (ExpressEnums.DIFFICULT.getStatus().equals(status)//疑难
                    || ExpressEnums.ABNORMAL_DELIVERY.getStatus().equals(status)//派件异常
                    || ExpressEnums.UNABLE_TO_CONTACT.getStatus().equals(status)//无法联系
                    || ExpressEnums.EXCEEDING_THE_AREA.getStatus().equals(status)) {//超区
                String baseContent = "您的包裹（%s%s）即将到达，请保持电话顺畅，确保及时送。\n特殊情况请联系平台客服";
                content = String.format(baseContent, ExpressDicUtil.getMapKey(expressCode), expressNo)+" %s";
            }
        } catch (Exception e) {
            log.error("处理异常订单短信内容出错:",e);
        }
        return content;
    }


    /**
     * 所有揽收状态
     */
    public String getMonitoringStatus(String status){
        Map<String,String> map = new HashMap<>();
        //在途
        map.put(ExpressEnums.IN_TRANSIT.getStatus(),ExpressEnums.IN_TRANSIT.getStatusName());
        //到达派件城市
        map.put(ExpressEnums.ARRIVING_THE_CITY.getStatus(),ExpressEnums.ARRIVING_THE_CITY.getStatusName());
        //干线
        map.put(ExpressEnums.MAIN_LINE.getStatus(),ExpressEnums.MAIN_LINE.getStatusName());
        //转递
        map.put(ExpressEnums.FORWARD.getStatus(),ExpressEnums.FORWARD.getStatusName());
        //转投
        map.put(ExpressEnums.TRANSFER.getStatus(),ExpressEnums.TRANSFER.getStatusName());
        //疑难
        map.put(ExpressEnums.DIFFICULT.getStatus(),ExpressEnums.DIFFICULT.getStatusName());
        String s = map.get(status);
        return s;
    }

    /**
     * 正则匹配文字判断是是否包裹已送达
     * @param content 最新的物流信息文本
     * @return boolean true 已送达，false 未送达
     */
    public boolean isDelivery(String content) {
        boolean result = false;
        if(StringUtils.isEmpty(content)){
            return result;
        }
        List<String> baseContent = new ArrayList<>();
        //定义正则表达式
        baseContent.add("由于您长时间未能取件，包裹将继续由");
        baseContent.add("您的包裹已送货上门，放至家门口");
        baseContent.add("请及时.*?取件");
        baseContent.add("请您凭取件码领取快件");
        baseContent.add("请凭取货码及时领取");
        baseContent.add("快件已.*?代收");
        baseContent.add("快件已暂存至");
        //正则匹配
        for (String regex : baseContent) {
            Matcher matcher = Pattern.compile(regex).matcher(content);
            while (matcher.find()){
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     * 是否忽略
     * true 忽略该条；false 不忽略
     */
    public boolean isFilterForUndelivered(QueryTrackResp resp){
        boolean result = false;
        Map<String, String> ignoreMap = new HashMap<>();
        //派件异常后签收
        ignoreMap.put(ExpressEnums.SIGN_FOR_EXCEPTION.getStatus(), ExpressEnums.SIGN_FOR_EXCEPTION.getStatusName());
        //本人签收
        ignoreMap.put(ExpressEnums.SIGNED_BY_MYSELF.getStatus(), ExpressEnums.SIGNED_BY_MYSELF.getStatusName());
        //签收
        ignoreMap.put(ExpressEnums.SIGN_FOR.getStatus(), ExpressEnums.SIGN_FOR.getStatusName());
        //退回
        ignoreMap.put(ExpressEnums.RETURN_BACK.getStatus(), ExpressEnums.RETURN_BACK.getStatusName());
        //退签
        ignoreMap.put(ExpressEnums.WITHDRAWAL.getStatus(), ExpressEnums.WITHDRAWAL.getStatusName());
        //拒收
        ignoreMap.put(ExpressEnums.REJECTION.getStatus(), ExpressEnums.REJECTION.getStatusName());
        //拒签
        ignoreMap.put(ExpressEnums.REFUSAL_TO_SIGN_FOR.getStatus(), ExpressEnums.REFUSAL_TO_SIGN_FOR.getStatusName());
        //销单
        ignoreMap.put(ExpressEnums.DO_DESTROY_ORDER.getStatus(), ExpressEnums.DO_DESTROY_ORDER.getStatusName());
        //代签
        ignoreMap.put(ExpressEnums.SIGN_ON_BEHALF_OF.getStatus(), ExpressEnums.SIGN_ON_BEHALF_OF.getStatusName());
        //投柜或驿站
        ignoreMap.put(ExpressEnums.DELIVERY_COUNTER_OR_STATION.getStatus(), ExpressEnums.DELIVERY_COUNTER_OR_STATION.getStatusName());
        //投柜或站签收
        ignoreMap.put(ExpressEnums.DELIVERY_OR_STATION_SIGNATURE.getStatus(), ExpressEnums.DELIVERY_OR_STATION_SIGNATURE.getStatusName());
        //柜或驿站超时未取
        ignoreMap.put(ExpressEnums.TIMED_OUT_NOT_GET.getStatus(), ExpressEnums.TIMED_OUT_NOT_GET.getStatusName());
        //超时未签收
        ignoreMap.put(ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatus(), ExpressEnums.OVERTIME_NOT_SIGNED_FOR.getStatusName());

        List<QueryTrackData> data = resp.getData();
        for (String key : ignoreMap.keySet()) {
            //判断所有节点中的状态
            for (QueryTrackData item : data) {
                String currentStatusCode = item.getStatusCode();
                if (StringUtils.isEmpty(currentStatusCode)) {
                    result = false;
                    break;
                } else if (key.equals(currentStatusCode)) {
                    result = true;
                    break;
                }
            }
            if (result) {
                break;
            }
        }
        if(!result && this.isFilterForRegex(resp.getData())){
            result = true;
        }
        return result;
    }

    /**
     * 针对超时未送达的异常需要过滤条件
     * true 匹配到，false 未匹配到
     */
    public boolean isFilterForRegex(List<QueryTrackData> data){
        boolean result = false;
        for (QueryTrackData item : data) {
            String content = item.getContext();
            if(StringUtils.isEmpty(content)){
                continue;
            }
            List<String> baseContent = new ArrayList<>();
            //定义正则表达式
            baseContent.add(".*?退回");
            baseContent.add(".*?拒收");
            baseContent.add(".*?拒签");
            baseContent.add("由于您长时间未能取件，包裹将继续由");
            baseContent.add("您的包裹已送货上门，放至家门口");
            baseContent.add("请及时.*?取件");
            baseContent.add("请.*?领取");
            baseContent.add("已.*?代.*?收");
            baseContent.add("已暂存至");
            baseContent.add("已存放至");
            baseContent.add(".*?已签收");
            baseContent.add("已在.*?暂放");
            baseContent.add("已在.*?暂放");
            //正则匹配
            for (String regex : baseContent) {
                Matcher matcher = Pattern.compile(regex).matcher(content);
                while (matcher.find()){
                    result = true;
                    break;
                }
                if(result){
                    break;
                }
            }
            if(result){
                break;
            }
        }
        return result;
    }

    /**
     * 正则匹配关键词
     * false - 匹配不存在，true - 已匹配到
     */
    public boolean isMatchRegex(List<QueryTrackData> data,List<String> regexs) {
        boolean result = false;
        for (QueryTrackData item : data) {
            String content = item.getContext();
            if(StringUtils.isEmpty(content)){
                continue;
            }
            //正则匹配
            for (String regex : regexs) {
                Matcher matcher = Pattern.compile(regex).matcher(content);
                while (matcher.find()){
                    result = true;
                    break;
                }
                if(result){
                    break;
                }
            }
            if(result){
                break;
            }
        }
        return result;
    }

    /**
     * 正则匹配文字判断是否已拒收
     * @return boolean true 已拒收，false 未拒收
     */
    public boolean isReject(List<QueryTrackData> data) {
        boolean result = false;
        for (QueryTrackData item : data) {
            String content = item.getContext();
            if(StringUtils.isEmpty(content)){
                continue;
            }
            List<String> baseContent = new ArrayList<>();
            //定义正则表达式
            baseContent.add(".*?拒收");
            baseContent.add(".*?拒签");
            //正则匹配
            for (String regex : baseContent) {
                Matcher matcher = Pattern.compile(regex).matcher(content);
                while (matcher.find()){
                    result = true;
                    break;
                }
                if(result){
                    break;
                }
            }
            if(result){
                break;
            }
        }
        return result;
    }

    /**
     * 正则匹配文字判断是否已退回
     * @return boolean true 退回中，false 未退回
     */
    public boolean isReturn(List<QueryTrackData> data) {
        boolean result = false;
        for (QueryTrackData item : data) {
            String content = item.getContext();
            if(StringUtils.isEmpty(content)){
                continue;
            }
            List<String> baseContent = new ArrayList<>();
            //定义正则表达式
            baseContent.add(".*?退回");
            //正则匹配
            for (String regex : baseContent) {
                Matcher matcher = Pattern.compile(regex).matcher(content);
                while (matcher.find()){
                    result = true;
                    break;
                }
                if(result){
                    break;
                }
            }
            if(result){
                break;
            }
        }
        return result;
    }

    /**
     * 正则匹配文字判断是是否一直处于 已揽收
     * @param content 最新的物流信息文本
     * @return boolean true 已匹配到，false 未匹配到
     */
    public boolean isReceived(String content) {
        boolean result = false;
        if(StringUtils.isEmpty(content)){
            return result;
        }
        List<String> baseContent = new ArrayList<>();
        //定义正则表达式
        baseContent.add(".*?已揽收");
        //正则匹配
        for (String regex : baseContent) {
            Matcher matcher = Pattern.compile(regex).matcher(content);
            while (matcher.find()){
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     * 入参时间是否超间隔时间（小时）
     * @param startDate 开始时间
     * @return boolean true:已超时 false:未超时
     */
    public boolean isTimeOut(Date startDate,long interval){
        boolean result = true;
        if (startDate != null) {
            long value = System.currentTimeMillis() - startDate.getTime();
            long valueHour = value / 1000 / 3600;
            //时间不超过 interval 小时，不记录异常
            if (valueHour < interval) {
                result = false;
            }
        }
        return result;
    }

    /**
     * 入参时间是距当前时间是否在minValue,bigValue之间
     * @param minValue 最小值(小时)
     * @param bigValue 最大值(小时)
     * @param baseDate 时间
     * @return boolean true:已超时 false:未超时
     */
    public  boolean isBetween(Long minValue,Long bigValue,Date baseDate){
        boolean result = false;
        long value = System.currentTimeMillis() - baseDate.getTime();
        long valueHour = value / 1000 / 3600;
        if(minValue == null && bigValue == null){
            return result;
        }
        if (minValue == null) {
            if(valueHour < bigValue){
                result = true;
            }
        }else if(bigValue == null){
            if(valueHour >= minValue){
                result = true;
            }
        }else {
            if( minValue <= valueHour &&  valueHour < bigValue){
                result = true;
            }
        }
        return result;
    }


    /**
     * 处理未录入快递单号的异常订单
     * @param bankerOrder
     * @param desc 异常描述
     * @param statusCode 异常状态值 -1:未录入快递单号 -2:查无物流
     * @return void
     */
    @Transactional(rollbackFor = Exception.class)
    public void handleExceptionOrderNoExpress(YxBankerOrder bankerOrder,String desc,Integer statusCode) {
        bankerOrder.setUpdateTime(null);
        bankerOrder.setExpressRecord(null);
        YxOrderException yxOrderException = orderExceptionMapper.selectByPrimaryKey(bankerOrder.getId());
        YxOrderException newOrderException = new YxOrderException();
        BeanUtils.copyProperties(bankerOrder,newOrderException);
        newOrderException.setStatus((byte)1);
        newOrderException.setStatusDesc(desc);
        newOrderException.setStatusCode(statusCode);
        //设置最新物流单号，可能订单物流已被修改
        newOrderException.setExpressCode(bankerOrder.getExpressCode());
        newOrderException.setExpressNo(bankerOrder.getExpressNo());
        newOrderException.setTaskUpdateTime(new Date());
        newOrderException.setOrderOn(bankerOrder.getOrderNo());
        newOrderException.setOrderCreateTime(bankerOrder.getCreateTime());
        newOrderException.setExceptionTime(new Date());
        if (null != bankerOrder.getBankerId()) {
            YxBanker banker = bankerMapper.selectByPrimaryKey(bankerOrder.getBankerId());
            newOrderException.setBankerName(banker.getName());
        }
        YxBankerOrder newBankerOrder = new YxBankerOrder();
        newBankerOrder.setStatus((byte) 2);
        if(yxOrderException == null){
            Date orderSyncTime = bankerOrder.getOrderSyncTime();
            orderSyncTime = Optional.ofNullable(orderSyncTime).orElse(bankerOrder.getCreateTime());
            if(!isTimeOut(orderSyncTime,24)){
                log.info("===距离订单同步时间不到24小时，无需记录查“未录入快递单号的异常”==={}", bankerOrder);
                return;
            }
            newOrderException.setCreateTime(new Date());
            orderExceptionMapper.insertSelective(newOrderException);
        }else {
            Date handleTime = yxOrderException.getHandleTime();
            if(!isTimeOut(handleTime,24)){
                log.info("===距离上次处理时间不到24小时，还是未录入快递单号，不更新当前订单==={}", bankerOrder);
                return;
            }
            newOrderException.setIsFinished(yxOrderException.getIsFinished());
            newOrderException.setCreateTime(yxOrderException.getCreateTime());
            orderExceptionMapper.updateByPrimaryKey(newOrderException);
        }
        bankerOrderMapper.updateByPrimaryKeySelective(newBankerOrder);
    }

    public YxOrderException selectOrderExceptionByPrimaryKey(Integer id) {
        return orderExceptionMapper.selectByPrimaryKey(id);
    }



    /**
     * 分页查询物流信息
     *
     * @param request
     * @return
     */
    public CommonPage getExpressOrdersList(ExpressOrderRequest request) {

        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        if (StringUtils.isNotBlank(request.getReturnExpressNo())) {
            List<YxExpressOrders> list = returnGoodsMapper.selectExpressOrders(request);
            if (!CollectionUtils.isEmpty(list)) {
                list.stream().forEach(item ->{
                    item.setQueryType(2);
                });
            }
            return CommonPage.restPage(list);
        }
        List<YxExpressOrders> list = expressOrdersMapper.queryExpressOrdersList(request);
        if (CollectionUtils.isEmpty(list)) {
            return CommonPage.restPage(list);
        }
        List<String> expressNoList = list.stream().map(YxExpressOrders::getExpressEno).collect(Collectors.toList());
        List<YxBankerOrder> bankerOrders = null ;
        if (!CollectionUtils.isEmpty(expressNoList)) {
            bankerOrders = bankerOrderMapper.selectByExpressNos(expressNoList);
        }
        List<YxBankerOrder> finalBankerOrders = bankerOrders;
        list.stream().forEach(item ->{
            if (!CollectionUtils.isEmpty(finalBankerOrders)) {
                Optional<YxBankerOrder> first = finalBankerOrders.stream().filter(order -> item.getExpressEno() !=null && item.getExpressEno().equals(order.getExpressNo())).findFirst();
                if (first.isPresent()) {
                    item.setUserName(first.get().getUserName());
                    String substring = first.get().getChildOrderNo().substring(0, 1);
                    if (substring.equals("MZ")) {
                        item.setOrderSource("yxyx");
                    }
//                    else if (substring.equals("D")) {
//                        item.setOrderSource("聚卖多");
//                    } else if (substring.equals("F")) {
//                        item.setOrderSource("xxxx商城");
//                    } else if (substring.equals("H")) {
//                        item.setOrderSource("臻芯良品");
//                    } else if (substring.equals("O")) {
//                        item.setOrderSource("xxxx严选");
//                    } else if (substring.equals("Q")) {
//                        item.setOrderSource("xxxx");
//                    } else if (substring.equals("S")) {
//                        item.setOrderSource("xxxx严选");
//                    }
                }
                item.setQueryType(1);
            }
        });
        return CommonPage.restPage(list);
    }



    /**
     * 更新物流信息
     *
     * @param expressId
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateExpressInfo(Integer expressId) {
        YxExpressOrders expressOrders = expressOrdersMapper.selectByPrimaryKey(expressId);
        if (null == expressOrders) {
            return;
        }
        try {
            String lockFlag = stringRedisTemplate.opsForValue().get(RedisConstants.EXPRESS_LOCK_KEY + expressOrders.getCompanyNo()+"-"+expressOrders.getExpressEno());
            if (null != lockFlag && "1".equals(lockFlag)) {
                return;
            }
        } catch (Exception e) {
            log.error("===获取快递锁定标志异常==={}", e);
        }
        QueryTrackResp resp = queryTrack(expressOrders.getCompanyNo(), expressOrders.getExpressEno(), expressOrders.getPhone());
        handleExceptionOrder(resp,expressOrders);
    }

    private QueryTrackResp queryTrack(String companyNo, String expressNo, String phone) {
        QueryTrack queryTrack = new QueryTrack();
        QueryTrackReq queryTrackReq = new QueryTrackReq();
        QueryTrackParam queryTrackParam = new QueryTrackParam();
        queryTrackParam.setCom(companyNo);
        queryTrackParam.setNum(expressNo);
        queryTrackParam.setPhone(phone);
        queryTrackReq.setParam(queryTrackParam);
        queryTrackReq.setCustomer(PropertiesReader.get("customer"));
        queryTrackReq.setSign(SignUtils.sign(new Gson().toJson(queryTrackParam) + PropertiesReader.get("key") + PropertiesReader.get("customer")));
        QueryTrackResp resp = queryTrack.queryTrack(queryTrackReq);
        return resp;
    }

    /**
     * 获得扫描快递单号锁
     * true-获取到锁；false-未获取到锁
     */
    public boolean getExpressLockForUpdate(String expressCompany, String expressNo) {
        String subKey = RedisConstants.EXPRESS_LOCK_KEY + expressCompany + "-" + expressNo;
        String value = redisService.get(subKey);
        if (StringUtils.isEmpty(value)) {
            //失效时间30分钟，快递100限制30分钟查询一次，否则锁单，返回500
            redisService.set(subKey,"1",30L,TimeUnit.MINUTES);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取补单物流信息
     * @param expressNo
     * @param expressCode
     * @param tel
     * @return QueryTrackResp
     */
    public QueryTrackResp getExpressInfoByReplacementOrder(String expressNo,String expressCode,String tel){
        //如果快递单号填写中文直接跳过
        Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]");
        Matcher sufUrlMatch = pattern.matcher(expressNo);
        if(org.springframework.util.StringUtils.isEmpty(expressNo) || org.springframework.util.StringUtils.isEmpty(expressCode) || sufUrlMatch.find()){
            return null;
        }
        Example example = new Example(YxReissueLogistics.class);
        example.createCriteria().andEqualTo("expressCompanyNo",expressCode).andEqualTo("expressNo",expressNo);
        example.orderBy("id").desc();
        List<YxReissueLogistics> yxReissueLogistics = reissueLogisticsMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(yxReissueLogistics)){
            return null;
        }
        YxReissueLogistics logistic = yxReissueLogistics.get(0);
        if (logistic.getLogisticsReceiptTime() == null || DateUtil.secondBetween(new Date(), logistic.getLogisticsReceiptTime()) >= DIFFERENCE_VALUE) {
            QueryTrack queryTrack = new QueryTrack();
            QueryTrackReq queryTrackReq = new QueryTrackReq();
            QueryTrackParam queryTrackParam = new QueryTrackParam();
            //特殊快递公司手机号为必填参数
            if(null != NeedPhoneExpressEnum.getExpressName(logistic.getExpressCompanyNo())){
                queryTrackParam.setPhone(logistic.getUserPhone());
            }
            queryTrackParam.setCom(logistic.getExpressCompanyNo());
            queryTrackParam.setNum(logistic.getExpressNo());
            queryTrackReq.setParam(queryTrackParam);
            queryTrackReq.setCustomer(PropertiesReader.get("customer"));
            queryTrackReq.setSign(SignUtils.sign(new Gson().toJson(queryTrackParam) + PropertiesReader.get("key") + PropertiesReader.get("customer")));
            QueryTrackResp resp = queryTrack.queryTrack(queryTrackReq);
            return resp;
        }else {
            String expressText = logistic.getExpressText();
            QueryTrackResp queryTrackResp = JSON.parseObject(expressText, QueryTrackResp.class);
            return queryTrackResp;
        }
    }

    public void testUndelivered() {
        String respStr = "{\"com\":\"yunda\",\"condition\":\"F00\",\"data\":[{\"context\":\"【潍坊市】您的包裹已被 九山快递超市前台 代签收，地址: 山东省潍坊市临朐县山东省潍坊市临朐县，如有疑问请电联快递员申杉杉(15265642223) ，投诉电话:0531-81929609\",\"ftime\":\"2024-03-23 20:28:57\",\"location\":\"潍坊市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-23 20:28:57\"},{\"areaCenter\":\"119.024836,36.7281\",\"areaCode\":\"CN370702000000\",\"areaName\":\"山东,潍坊市,潍城区\",\"areaPinYin\":\"wei cheng qu\",\"context\":\"【潍坊市】山东潍坊临朐县军祥服务部[0536-5014232] 快递员 申杉杉(15265642223) 正在为您派送【95121为韵达快递员外呼专属号码，请放心接听】\",\"ftime\":\"2024-03-23 17:02:48\",\"location\":\"潍坊市\",\"status\":\"派件\",\"statusCode\":\"5\",\"time\":\"2024-03-23 17:02:48\"},{\"areaCenter\":\"119.161755,36.706774\",\"areaCode\":\"CN370700000000\",\"areaName\":\"山东,潍坊市\",\"areaPinYin\":\"wei fang shi\",\"context\":\"【潍坊市】已到达 山东潍坊临朐县军祥服务部[0536-5014232]\",\"ftime\":\"2024-03-23 17:02:18\",\"location\":\"潍坊市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-23 17:02:18\"},{\"areaCenter\":\"119.161755,36.706774\",\"areaCode\":\"CN370700000000\",\"areaName\":\"山东,潍坊市\",\"areaPinYin\":\"wei fang shi\",\"context\":\"【潍坊市】已到达 山东潍坊临朐县军祥服务部[0536-5014232]\",\"ftime\":\"2024-03-23 15:10:06\",\"location\":\"潍坊市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-23 15:10:06\"},{\"areaCenter\":\"119.161755,36.706774\",\"areaCode\":\"CN370700000000\",\"areaName\":\"山东,潍坊市\",\"areaPinYin\":\"wei fang shi\",\"context\":\"【潍坊市】已离开 山东潍坊分拨交付中心 发往 山东潍坊临朐县军祥服务部\",\"ftime\":\"2024-03-23 10:51:23\",\"location\":\"潍坊市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-23 10:51:23\"},{\"areaCenter\":\"119.161755,36.706774\",\"areaCode\":\"CN370700000000\",\"areaName\":\"山东,潍坊市\",\"areaPinYin\":\"wei fang shi\",\"context\":\"【潍坊市】已到达 山东潍坊分拨交付中心\",\"ftime\":\"2024-03-23 10:29:33\",\"location\":\"潍坊市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-23 10:29:33\"},{\"areaCenter\":\"120.894291,31.980171\",\"areaCode\":\"CN320600000000\",\"areaName\":\"江苏,南通市\",\"areaPinYin\":\"nan tong shi\",\"context\":\"【南通市】已离开 江苏南通分拨交付中心 发往 山东潍坊分拨交付中心\",\"ftime\":\"2024-03-22 22:19:17\",\"location\":\"南通市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-22 22:19:17\"},{\"areaCenter\":\"120.894291,31.980171\",\"areaCode\":\"CN320600000000\",\"areaName\":\"江苏,南通市\",\"areaPinYin\":\"nan tong shi\",\"context\":\"【南通市】已到达 江苏南通分拨交付中心\",\"ftime\":\"2024-03-22 22:17:44\",\"location\":\"南通市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-22 22:17:44\"},{\"areaCenter\":\"120.894291,31.980171\",\"areaCode\":\"CN320600000000\",\"areaName\":\"江苏,南通市\",\"areaPinYin\":\"nan tong shi\",\"context\":\"【南通市】已离开 江苏南通公司 发往 潍坊地区包\",\"ftime\":\"2024-03-22 21:59:56\",\"location\":\"南通市\",\"status\":\"在途\",\"statusCode\":\"0\",\"time\":\"2024-03-22 21:59:56\"},{\"areaCenter\":\"121.0873299,32.0901012\",\"areaCode\":\"CN320612001000\",\"areaName\":\"江苏,南通市,通州区,金沙\",\"areaPinYin\":\"jin sha jie dao\",\"context\":\"【南通市】江苏南通通州金沙服务部袁灶便民寄存点-蔡云中（18851322796） 已揽收\",\"ftime\":\"2024-03-22 16:45:14\",\"location\":\"南通市\",\"status\":\"揽收\",\"statusCode\":\"1\",\"time\":\"2024-03-22 16:45:14\"}],\"ischeck\":\"0\",\"message\":\"ok\",\"nu\":\"433794654405164\",\"result\":false,\"routeInfo\":{\"cur\":{},\"from\":{}},\"state\":\"201\",\"status\":\"200\"}";
        QueryTrackResp resp = JSON.parseObject(respStr, QueryTrackResp.class);
        if(!isFilterForUndelivered(resp)){
            System.out.println("========>符合超时未送达条件！");
        }else {
            System.out.println("========>不符合");
        }
    }
}
